#include "gpio_BAT32G157.h"

#include <string.h>
#include <stdio.h>
#include "BAT32G157.h"
#include "gpio.h"
#ifdef CONFIG_PLATFORM_GPIO_IRQ
#include "intp.h"
#include "key.h"
#endif
#include "insdrv_gpio.h"
#include "insdrv_i2c.h"

// #if(PLATFORM_CHIP == PLATFORM_BAT32G157)
#if 1
int32_t InsDrv_Gpio_Init(InsDrv_Gpio_Group_Config_t *p_gpio_cfg)
__ATTRIB_ALIAS__(InsDrv_Gpio_BAT32G157_Init);

void InsDrv_Gpio_SetMode(InsDrv_Gpio_Port_e port, InsDrv_Gpio_Pin_e pin, InsDrv_Gpio_Mode_e mode) 
__ATTRIB_ALIAS__(InsDrv_Gpio_BAT32G157_SetMode);

void InsDrv_Gpio_Output(InsDrv_Gpio_Port_e port, InsDrv_Gpio_Pin_e pin, InsDrv_Gpio_Level_e level) 
__ATTRIB_ALIAS__(InsDrv_Gpio_BAT32G157_Output);

InsDrv_Gpio_Level_e InsDrv_Gpio_GetPinLevel(InsDrv_Gpio_Port_e port, InsDrv_Gpio_Pin_e pin) 
__ATTRIB_ALIAS__(InsDrv_Gpio_BAT32G157_GetPinLevel);

void InsDrv_Gpio_Toggle(InsDrv_Gpio_Port_e port, InsDrv_Gpio_Pin_e pin)
__ATTRIB_ALIAS__(InsDrv_Gpio_BAT32G157_Toggle);

void InsDrv_Gpio_SetPullCtrl(InsDrv_Gpio_Port_e port, InsDrv_Gpio_Pin_e pin, InsDrv_Gpio_PullMode_e pull_mode) 
__ATTRIB_ALIAS__(InsDrv_Gpio_BAT32G157_SetPullCtrl);

#ifdef CONFIG_PLATFORM_GPIO_IRQ
void InsDrv_Gpio_IsrHook(InsDrv_Gpio_Port_e port, InsDrv_Gpio_Pin_e pin, InsDrv_Gpio_Isr_f isr)
__ATTRIB_ALIAS__(InsDrv_Gpio_BAT32G157_IsrHook);

void InsDrv_Gpio_EnableInt(InsDrv_Gpio_Port_e port, InsDrv_Gpio_Pin_e pin, InsDrv_Gpio_IntType_e int_type)
__ATTRIB_ALIAS__(InsDrv_Gpio_BAT32G157_EnableInt);

void InsDrv_Gpio_DisableInt(InsDrv_Gpio_Port_e port, InsDrv_Gpio_Pin_e pin)
__ATTRIB_ALIAS__(InsDrv_Gpio_BAT32G157_DisableInt);
#endif

#ifdef CONFIG_PLATFORM_GPIO_IRQ
void IRQ01_Handler(void) __ATTRIB_ALIAS__(InsDrv_Gpio_BAT32G157_IntP0_Isr);
void IRQ02_Handler(void) __ATTRIB_ALIAS__(InsDrv_Gpio_BAT32G157_IntP1_Isr);
void intp2_handler(void) __ATTRIB_ALIAS__(InsDrv_Gpio_BAT32G157_IntP2_Isr);
void intp3_handler(void) __ATTRIB_ALIAS__(InsDrv_Gpio_BAT32G157_IntP3_Isr);
void intp4_handler(void) __ATTRIB_ALIAS__(InsDrv_Gpio_BAT32G157_IntP4_Isr);
void intp5_handler(void) __ATTRIB_ALIAS__(InsDrv_Gpio_BAT32G157_IntP5_Isr);
void intp6_handler(void) __ATTRIB_ALIAS__(InsDrv_Gpio_BAT32G157_IntP6_Isr);
void intp7_handler(void) __ATTRIB_ALIAS__(InsDrv_Gpio_BAT32G157_IntP7_Isr);
void key_interrupt(void) __ATTRIB_ALIAS__(InsDrv_Gpio_BAT32G157_Key_Isr);
#endif

#ifdef CONFIG_PLATFORM_GPIO_IRQ
typedef struct _InsDrv_Gpio_BAT32G157_Int_s
{
    InsDrv_Gpio_Port_e port;
    InsDrv_Gpio_Pin_e pin;
    InsDrv_Gpio_Isr_f isr;
    uint16_t int_channel;
}InsDrv_Gpio_BAT32G157_Int_t;

#define INSDRV_GPIO_BAT32G157_EINT_NUM (8)
static InsDrv_Gpio_BAT32G157_Int_t g_gpio_BAT32G157_eint_map[INSDRV_GPIO_BAT32G157_EINT_NUM] = 
{
    {INSDRV_GPIO_PORTC, INSDRV_GPIO_PIN_7,  NULL, INSDRV_GPIO_EINT0},
    {INSDRV_GPIO_PORTC, INSDRV_GPIO_PIN_8,  NULL, INSDRV_GPIO_EINT1},
    {INSDRV_GPIO_PORTA, INSDRV_GPIO_PIN_0,  NULL, INSDRV_GPIO_EINT2},
    {INSDRV_GPIO_PORTA, INSDRV_GPIO_PIN_4,  NULL, INSDRV_GPIO_EINT3},
    {INSDRV_GPIO_PORTD, INSDRV_GPIO_PIN_0,  NULL, INSDRV_GPIO_EINT4},
    {INSDRV_GPIO_PORTD, INSDRV_GPIO_PIN_4,  NULL, INSDRV_GPIO_EINT5},
    {INSDRV_GPIO_PORTB, INSDRV_GPIO_PIN_0,  NULL, INSDRV_GPIO_EINT6},
    {INSDRV_GPIO_PORTB, INSDRV_GPIO_PIN_3,  NULL, INSDRV_GPIO_EINT7},
};

#define INSDRV_GPIO_BAT32G157_PORT_INT_NUM (8)
static InsDrv_Gpio_BAT32G157_Int_t g_gpio_BAT32G157_port_map[INSDRV_GPIO_BAT32G157_PORT_INT_NUM] = 
{
    {INSDRV_GPIO_PORTC, INSDRV_GPIO_PIN_6,  NULL, KR0_CHAN},
    {INSDRV_GPIO_PORTC, INSDRV_GPIO_PIN_7,  NULL, KR1_CHAN},
    {INSDRV_GPIO_PORTC, INSDRV_GPIO_PIN_12, NULL, KR2_CHAN},
    {INSDRV_GPIO_PORTC, INSDRV_GPIO_PIN_13, NULL, KR3_CHAN},
    {INSDRV_GPIO_PORTC, INSDRV_GPIO_PIN_14, NULL, KR4_CHAN},
    {INSDRV_GPIO_PORTC, INSDRV_GPIO_PIN_15, NULL, KR5_CHAN},
    {INSDRV_GPIO_PORTC, INSDRV_GPIO_PIN_8,  NULL, KR6_CHAN},
    {INSDRV_GPIO_PORTC, INSDRV_GPIO_PIN_9,  NULL, KR7_CHAN},
};
#endif

int32_t InsDrv_Gpio_BAT32G157_Init(InsDrv_Gpio_Group_Config_t *p_gpio_cfg)
{
    int8_t i;
    uint16_t value;
    uint16_t ori_value;

    uint16_t mask;
    PORT_TypeDef port_x;

    if(!p_gpio_cfg)
    {
        return INSERR_NG;
    }

    for(i = 0; i < PLATFORM_GPIO_GROUP_NUM; i++)
    {

        if(p_gpio_cfg->pin_group[i].port >= INSDRV_GPIO_PORT_NUM
            || p_gpio_cfg->pin_group[i].port == INSDRV_GPIO_PORTE
            || p_gpio_cfg->pin_group[i].port == INSDRV_GPIO_PORTF
            || p_gpio_cfg->pin_group[i].port == INSDRV_GPIO_PORTK)
        {
            return INSERR_NG;
        }

        port_x = (PORT_TypeDef)p_gpio_cfg->pin_group[i].port;
        mask = p_gpio_cfg->pin_group[i].mask;

        //mode_ctrl
        ori_value = *((volatile uint16_t*)(&PORT->PMCA + port_x));
        ori_value &= (~mask);//clean
        value = p_gpio_cfg->pin_group[i].mode_ctrl & mask;
        value |= ori_value;
        *((volatile uint16_t*)(&PORT->PMCA + port_x)) = value;

        //direction
        value = p_gpio_cfg->pin_group[i].direction;
	    *((volatile uint16_t*)(&PORT->PMA + port_x)) = (0xff & (~mask))|(value & mask);

        //output_mode
        value = p_gpio_cfg->pin_group[i].output_mode & mask;
        *((volatile uint16_t*)(&PORT->POMA + port_x)) = value;
        
        //pull_down(157不支持下拉)
        // value = p_gpio_cfg->pin_group[i].pull_down & mask;
        // *((volatile uint16_t*)(&PORT->PD0 + port_x)) = value;

        //pull_up
        ori_value = *((volatile uint16_t*)(&PORT->PUA + port_x));
        ori_value &= (~mask);//clean
        value = p_gpio_cfg->pin_group[i].pull_up & mask;
        value |= ori_value;
        *((volatile uint16_t*)(&PORT->PUA + port_x)) = value;

        //data
        value = p_gpio_cfg->pin_group[i].data & mask;
        *((volatile uint16_t*)(&PORT->PA + port_x)) = value;
    }
	return INSERR_OK;
}

void InsDrv_Gpio_Disable_MCU_USB(void)
{
    //PORT_DisableUSB();
}

void InsDrv_Gpio_Enable_MCU_USBPin(void)
{
    //PORT_USBPIN_Enable();
}

void InsDrv_Gpio_Disable_MCU_USBPin(void)
{
    //PORT_USBPIN_Disable();
}

void InsDrv_Gpio_BAT32G157_SetMode(InsDrv_Gpio_Port_e port, InsDrv_Gpio_Pin_e pin, InsDrv_Gpio_Mode_e mode)
{
    if(port >= INSDRV_GPIO_PORT_NUM || pin >= INSDRV_GPIO_PIN_NUMS)
    {
        return;
    }

    if(mode == INSDRV_GPIO_MODE_INPUT)
    {
        PORT_Init((PORT_TypeDef)port, (PIN_TypeDef)pin, INPUT);
    }
    else if(mode == INSDRV_GPIO_MODE_OUTPUT)
    {
        PORT_Init((PORT_TypeDef)port, (PIN_TypeDef)pin, OUTPUT);
    }
    else if(mode == INSDRV_GPIO_MODE_OD_OUTPUT)
    {
        PORT_Init((PORT_TypeDef)port, (PIN_TypeDef)pin, OPENDRAIN_OUTPUT);
    }  
}

void InsDrv_Gpio_BAT32G157_Output(InsDrv_Gpio_Port_e port, InsDrv_Gpio_Pin_e pin, InsDrv_Gpio_Level_e level)
{
    if(port >= INSDRV_GPIO_PORT_NUM || pin >= INSDRV_GPIO_PIN_NUMS)
    {
        return;
    }

    if(level == INSDRV_GPIO_LEVEL_LOW)
    {
        PORT_ClrBit((PORT_TypeDef)port, (PIN_TypeDef)pin);
    }
    else if(level == INSDRV_GPIO_LEVEL_HIGH)
    {
        PORT_SetBit((PORT_TypeDef)port, (PIN_TypeDef)pin);
    }
}

InsDrv_Gpio_Level_e InsDrv_Gpio_BAT32G157_GetPinLevel(InsDrv_Gpio_Port_e port, InsDrv_Gpio_Pin_e pin)
{
    InsDrv_Gpio_Level_e level = INSDRV_GPIO_LEVEL_NUM;

    if(port >= INSDRV_GPIO_PORT_NUM || pin >= INSDRV_GPIO_PIN_NUMS)
    {
        return INSDRV_GPIO_LEVEL_NUM;
    }

    level = (InsDrv_Gpio_Level_e)(PORT_GetBit((PORT_TypeDef)port, (PIN_TypeDef)pin)?INSDRV_GPIO_LEVEL_HIGH:INSDRV_GPIO_LEVEL_LOW);
    //PORT->PMS = 0;
    return level;
}

void InsDrv_Gpio_BAT32G157_Toggle(InsDrv_Gpio_Port_e port, InsDrv_Gpio_Pin_e pin)
{
    if(port >= INSDRV_GPIO_PORT_NUM || pin >= INSDRV_GPIO_PIN_NUMS)
    {
        return;
    }

    PORT_ToggleBit((PORT_TypeDef)port, (PIN_TypeDef)pin);
}

void InsDrv_Gpio_BAT32G157_SetPullCtrl(InsDrv_Gpio_Port_e port, InsDrv_Gpio_Pin_e pin, InsDrv_Gpio_PullMode_e pull_mode)
{
    if(port >= INSDRV_GPIO_PORT_NUM || pin >= INSDRV_GPIO_PIN_NUMS)
    {
        return ;
    }

    if(pull_mode == INSDRV_GPIO_PULLUP)
    {
        GPIO_PullUp_Enable((__IO uint16_t *)(&PORT->PA + port), INSDRV_GPIO_PINMASK(pin));
    }

    else if(pull_mode == INSDRV_GPIO_NOPULL)
    {
        GPIO_PullUp_Disable((__IO uint16_t *)(&PORT->PA + port), INSDRV_GPIO_PINMASK(pin));
    }
}

#ifdef CONFIG_PLATFORM_GPIO_IRQ
void InsDrv_Gpio_BAT32G157_IsrHook(InsDrv_Gpio_Port_e port, InsDrv_Gpio_Pin_e pin, InsDrv_Gpio_Isr_f isr)
{
    int i;

    if(port >= INSDRV_GPIO_PORT_NUM || pin >= INSDRV_GPIO_PIN_NUMS)
    {
        return ;
    }

    for(i = 0; i < INSDRV_GPIO_BAT32G157_EINT_NUM; i++)
    {
        if(g_gpio_BAT32G157_eint_map[i].port == port 
            && g_gpio_BAT32G157_eint_map[i].pin == pin)
        {
            //printf("IsrHook port=%d,pin=%d\r\n",port,pin);
            g_gpio_BAT32G157_eint_map[i].isr = isr;
            return;
        }
    }

    for(i = 0; i < INSDRV_GPIO_BAT32G157_PORT_INT_NUM; i++)
    {
        if(g_gpio_BAT32G157_port_map[i].port == port 
            && g_gpio_BAT32G157_port_map[i].pin == pin)
        {
            g_gpio_BAT32G157_port_map[i].isr = isr;
            return;
        }
    }
}

void InsDrv_Gpio_BAT32G157_EnableInt(InsDrv_Gpio_Port_e port, InsDrv_Gpio_Pin_e pin, InsDrv_Gpio_IntType_e int_type)
{
    uint8_t i = 0;
    uint16_t pin_mask = 0;
    //uint8_t value = 0;

    if(port >= INSDRV_GPIO_PORT_NUM || pin >= INSDRV_GPIO_PIN_NUMS || int_type >= INSDRV_GPIO_INT_NUM)
    {
        return;
    }
    //return;
    for(i = 0; i < INSDRV_GPIO_BAT32G157_EINT_NUM; i++)
    {
        if(g_gpio_BAT32G157_eint_map[i].port == port 
            && g_gpio_BAT32G157_eint_map[i].pin == pin)
        {            
            pin_mask = 0x01 << g_gpio_BAT32G157_eint_map[i].int_channel;
            //printf("pin_mask=%d,pin=%d,int_channel=%d\r\n",pin_mask,pin,g_gpio_BAT32G157_eint_map[i].int_channel);
            INTP_Init(pin_mask, (intp_edge_t)int_type);
            INTP_Start(pin_mask);
            return;
        }
    }

    for(i = 0; i < INSDRV_GPIO_BAT32G157_PORT_INT_NUM; i++)
    {
        if(g_gpio_BAT32G157_port_map[i].port == port 
            && g_gpio_BAT32G157_port_map[i].pin == pin)
        {
            KEY_Stop();
            pin_mask = 0x01 << g_gpio_BAT32G157_port_map[i].pin;
            //value = g_gpio_BAT32G157_port_map[i].int_channel;
            //KEY_Init(pin_mask, g_gpio_BAT32G157_port_map[i].int_channel);
            KEY_Start();
            return;
        }
    }
}

void InsDrv_Gpio_BAT32G157_DisableInt(InsDrv_Gpio_Port_e port, InsDrv_Gpio_Pin_e pin)
{
    uint8_t i;
    uint16_t pin_mask;
    //uint8_t value;
    
    if(port >= INSDRV_GPIO_PORT_NUM || pin >= INSDRV_GPIO_PIN_NUMS)
    {
        return;
    }

    for(i = 0; i < INSDRV_GPIO_BAT32G157_EINT_NUM; i++)
    {
        if(g_gpio_BAT32G157_eint_map[i].port == port 
            && g_gpio_BAT32G157_eint_map[i].pin == pin)
        {
            pin_mask = 0x01 << g_gpio_BAT32G157_eint_map[i].int_channel;
            INTP_Stop(pin_mask);
            return;
        }
    }   

    for(i = 0; i < INSDRV_GPIO_BAT32G157_PORT_INT_NUM; i++)
    {
        if(g_gpio_BAT32G157_port_map[i].port == port 
            && g_gpio_BAT32G157_port_map[i].pin == pin)
        {
            //KEY_Stop();
            KEY->KRM &= ~g_gpio_BAT32G157_port_map[i].int_channel;
            return;
        }
    }
}

static void InsDrv_Gpio_BAT32G157_Int_Callback(InsDrv_Gpio_EInt_Num_e eint)
{
    uint32_t i = 0;    
    //printf("eint = %d\r\n",eint);
    for(i=0; i<INSDRV_GPIO_BAT32G157_EINT_NUM; i++)
    {
        if(g_gpio_BAT32G157_eint_map[i].int_channel != eint 
        || g_gpio_BAT32G157_eint_map[i].isr == NULL)
        {
            continue;
        }
        g_gpio_BAT32G157_eint_map[i].isr();
    }
}

void InsDrv_Gpio_BAT32G157_IntP0_Isr(void)
{
    INTC_ClearPendingIRQ(INTP0_IRQn); 
    InsDrv_Gpio_BAT32G157_Int_Callback(INSDRV_GPIO_EINT0);
}

void InsDrv_Gpio_BAT32G157_IntP1_Isr(void)
{
    INTC_ClearPendingIRQ(INTP1_IRQn); 
    InsDrv_Gpio_BAT32G157_Int_Callback(INSDRV_GPIO_EINT1);
}

void InsDrv_Gpio_BAT32G157_IntP2_Isr(void)
{
    INTC_ClearPendingIRQ(INTP2_IRQn); 
    InsDrv_Gpio_BAT32G157_Int_Callback(INSDRV_GPIO_EINT2);
}

void InsDrv_Gpio_BAT32G157_IntP3_Isr(void)
{
    INTC_ClearPendingIRQ(INTP3_IRQn); 
    InsDrv_Gpio_BAT32G157_Int_Callback(INSDRV_GPIO_EINT3);
}

void InsDrv_Gpio_BAT32G157_IntP4_Isr(void)
{
    INTC_ClearPendingIRQ(INTP4_IRQn); 
    InsDrv_Gpio_BAT32G157_Int_Callback(INSDRV_GPIO_EINT4);
}

void InsDrv_Gpio_BAT32G157_IntP5_Isr(void)
{
    INTC_ClearPendingIRQ(INTP5_IRQn); 
    InsDrv_Gpio_BAT32G157_Int_Callback(INSDRV_GPIO_EINT5);
}

void InsDrv_Gpio_BAT32G157_IntP6_Isr(void)
{
    INTC_ClearPendingIRQ(INTP6_IRQn);
    InsDrv_Gpio_BAT32G157_Int_Callback(INSDRV_GPIO_EINT6);
}

void InsDrv_Gpio_BAT32G157_IntP7_Isr(void)
{
    INTC_ClearPendingIRQ(INTP7_IRQn); 
    InsDrv_Gpio_BAT32G157_Int_Callback(INSDRV_GPIO_EINT7);
}

void InsDrv_Gpio_BAT32G157_Key_Isr(void)
{
    uint8_t i;
    InsDrv_Gpio_Level_e level = INSDRV_GPIO_LEVEL_NUM;

    INTC_ClearPendingIRQ(KEY_IRQn); 

    for(i = 0; i < INSDRV_GPIO_BAT32G157_PORT_INT_NUM; i++)
    {
        level = InsDrv_Gpio_BAT32G157_GetPinLevel(g_gpio_BAT32G157_port_map[i].port, g_gpio_BAT32G157_port_map[i].pin);
        if(level == INSDRV_GPIO_LEVEL_LOW)
        {
            if(g_gpio_BAT32G157_port_map[i].isr)
            {
                g_gpio_BAT32G157_port_map[i].isr();
            }
        }
    }
}
#endif

#endif
